using System;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Xml.Linq;

using Patterns.Tools.CodeGenerators.GoogleCode.Enums;

namespace Patterns.Tools.CodeGenerators.GoogleCode
{
	public static class WikiTypeEngine
	{
		public static ScanResults Run(Type objectType, XElement xml, string sidebarName, string wikiUri, string sourceUri)
		{
			string name = WikiNames.Get(objectType);

			return new ScanResults
			{
				Name = name,
				ParentName = WikiHelper.GetParentWikiName(true, WikiHelper.GetParentName(objectType.FullName)),
				Content = GetWikiTypeContent(objectType, xml, sidebarName, wikiUri, sourceUri)
			};
		}

		private static string GetWikiTypeContent(Type objectType, XElement xml, string sidebarName, string wikiUri, string sourceUri)
		{
			if (objectType.IsEnum) return RenderEnum(objectType, xml, sidebarName, wikiUri, sourceUri);
			return objectType.IsInterface
				? RenderInterface(objectType, xml, sidebarName, wikiUri, sourceUri)
				: RenderClass(objectType, xml, sidebarName, wikiUri, sourceUri);
		}

		private static string RenderClass(Type objectType, XElement xml, string sidebarName, string wikiUri, string sourceUri)
		{
			if (objectType.IsSealed && !objectType.IsGenericType && !objectType.IsNested)
			{
				MethodInfo[] extensionMethods = objectType.GetMethods(BindingFlags.Static | BindingFlags.Public)
					.Where(method => method.IsDefined(typeof (ExtensionAttribute), false))
					.Where(method => method.GetParameters().Any())
					.ToArray();
			}
			return "#sidebar " + sidebarName + Environment.NewLine + string.Format("{0} documentation coming soon", objectType.Name);
		}

		private static string RenderInterface(Type objectType, XElement xml, string sidebarName, string wikiUri, string sourceUri)
		{
			return "#sidebar " + sidebarName + Environment.NewLine + string.Format("{0} documentation coming soon", objectType.Name);
		}

		private static string RenderEnum(Type objectType, XElement xml, string sidebarName, string wikiUri, string sourceUri)
		{
			return new GoogleWikiEnum
			{
				Name = objectType.FullName,
				Namespace = objectType.Namespace,
				SidebarName = sidebarName,
				SourceUri = sourceUri,
				WikiUri = wikiUri,
				Summary = WikiHelper.GetTypeSummary(objectType, xml),
				Options = Enum.GetValues(objectType).OfType<object>()
					.ToDictionary(item => item.ToString(), item => WikiHelper.GetEnumOptionSummary(objectType, item.ToString(), xml))
			}.TransformText();
		}
	}
}